import os, sys
import waflib.Task, waflib.TaskGen
from waflib.TaskGen import extension, extension
from waf_dynamo import new_copy_task
import zipfile

blddir = 'build'

def create_simple_protoc_task(name, ext, compiled_ext, type, before, shell = True, color = 'PINK'):
    def create(self, node):
        task = self.create_task(name)
        task.set_inputs(node)
        out = node.change_ext(compiled_ext)
        task.set_outputs(out)

    cmd = 'protoc --encode=%s -I ../src/test -I ${DYNAMO_HOME}/share/proto ../src/test/test_resource_ddf.proto < ${SRC} > ${TGT}' % type
    waflib.Task.task_factory(name, cmd, before=before, shell=shell, color=color)
    extension(ext)(create)

create_simple_protoc_task('testresourcecont', '.cont_pb', '.cont', 'TestResource.ResourceContainerDesc', before='c cxx')
create_simple_protoc_task('resourcefoo', '.foo_pb', '.foo', 'TestResource.ResourceFoo', before='c cxx')

# Test archive data. Only copy the source data.
new_copy_task('ad', '.ad', '.adc')
new_copy_task('script', '.script', '.scriptc')


def add_to_zip_file(task):
    cwd = task.cwd.abspath()
    with zipfile.ZipFile(task.outputs[0].abspath(), 'a') as zipf:
        for i in task.inputs:
            src = i.get_bld().abspath()
            name, ext = os.path.splitext(src)
            ext = ext.replace('.ad', '.adc')
            ext = ext.replace('.script', '.scriptc')
            src = name + ext
            dst = os.path.relpath(src, cwd)
            zipf.write(src, dst)


def build(bld):
    resources = bld(source = ['test.cont_pb', 'test_ref.cont_pb', 'empty.script'])

    # Create an archive without any liveupdate content
    sources = ['archive_data/%s' % e for e in ['file4.ad', 'file1.ad', 'file3.ad', 'file2.ad', 'file5.script']]
    archive = bld(features='barchive',
                  source_root='src/test',
                  resource_name='resources_no_lu',
                  use_compression=False,
                  source=' '.join(sources))

    bld.add_group()

    # ArchiveBuilder (in test mode) automatically marks files with "liveupdate" as excluded resources
    sources = ['archive_data/%s' % e for e in ['file4.ad', 'file1.ad', 'file3.ad', 'file2.ad', 'file5.script', 'liveupdate.file7.ad', 'liveupdate.file6.script']]

    archive = bld(features='barchive',
                  source_root='src/test',
                  resource_name='resources',
                  use_compression=False,
                  source=' '.join(sources))

    bld.add_group()

    archive_compressed = bld(features='barchive',
                             source_root='src/test',
                             resource_name='resources_compressed',
                             use_compression=True,
                             source=' '.join(sources))

    bld.add_group()

    bld(features='barchive',
        source_root='src/test',
        name='luresources',
        resource_name='luresources',
        use_compression=False,
        source=' '.join(sources))

    bld.add_group()

    bld(features='barchive',
        source_root='src/test',
        resource_name='luresources_compressed',
        use_compression=True,
        source=' '.join(sources))

    bld.add_group()

    bld(features='barchive',
         source_root='src/test',
         resource_name='resources_pb',
         use_compression=False,
         source=bld.path.ant_glob('*.*_pb'))

    bld.add_group()

    bld(source = bld.path.ant_glob('overrides/**/*.*') + bld.path.ant_glob('zipfiles/**/*.*'),
        name = 'overides')

    bld.add_group()

    bld(rule = add_to_zip_file,
        target = bld.path.find_or_declare('luresources.zip'),
        source = bld.path.ant_glob('zipfiles/**/*'),
        cwd = bld.path.find_or_declare('zipfiles'),
        after = ['luresources', 'overides'])

    bld.add_group()

    defines = []
    if not ('GITHUB_CI' in bld.env.DEFINES and sys.platform == 'darwin'):
        defines = ['DM_TEST_HTTP_SUPPORTED']
    if bld.env.PLATFORM in ['arm64-nx64']:
        defines = []

    # ******************************************************************************************************************************

    test_block_allocator = bld.program(features = 'cxx test',
                                       includes = '..',
                                       use      = 'TESTMAIN DLIB THREAD resource',
                                       target   = 'test_block_allocator',
                                       source   = 'test_block_allocator.cpp')

    # ******************************************************************************************************************************
    # Resource providers
    skip_http_test = []
    if bld.env.PLATFORM in ['wasm-web','wasm_pthread-web','js-web']:
        skip_http_test = ['skip_test']

    bld.program(features     = 'cxx test',
                includes     = '.. ../../proto',
                use          = 'TESTMAIN DDF DLIB PROFILE_NULL SOCKET THREAD LUA resource',
                exported_symbols = ['ResourceProviderFile'],
                target       = 'test_provider_file',
                source       = 'test_provider_file.cpp',)

    embed_source = []
    for name in ['resources', 'resources_compressed', 'resources_no_lu']:
        embed_source.append(name + '.arci')
        embed_source.append(name + '.arcd')
        embed_source.append(name + '.dmanifest')

    bld.program(features     = 'cxx embed test',
                includes     = '.. ../../proto',
                use          = 'TESTMAIN DDF DLIB PROFILE_NULL SOCKET THREAD LUA resource',
                exported_symbols = ['ResourceProviderArchive'],
                target       = 'test_provider_archive',
                source       = 'test_provider_archive.cpp',
                embed_source = embed_source)

    bld.program(features = 'cxx embed test',
                includes     = '.. ../../proto',
                use          = 'TESTMAIN DDF DLIB PROFILE_NULL SOCKET THREAD LUA resource',
                exported_symbols = ['ResourceProviderArchive', 'ResourceProviderArchiveMutable'],
                target       = 'test_provider_archive_mutable',
                source       = 'test_provider_archive_mutable.cpp',
                embed_source = embed_source)

    bld.program(features     = ['cxx', 'test'] + skip_http_test,
                includes     = '.. ../../proto',
                defines      = defines,
                use          = 'TESTMAIN DDF DLIB PROFILE_NULL SOCKET THREAD LUA resource',
                exported_symbols = ['ResourceProviderHttp'],
                target       = 'test_provider_http',
                source       = 'test_provider_http.cpp')

    bld.program(features     = 'cxx test',
                includes     = '.. ../../proto',
                use          = 'TESTMAIN DDF DLIB PROFILE_NULL SOCKET THREAD LUA resource',
                exported_symbols = ['ResourceProviderZip'],
                target       = 'test_provider_zip',
                source       = 'test_provider_zip.cpp',)

    bld.program(features     = 'cxx test',
                includes     = '.. ../../proto',
                use          = 'TESTMAIN DDF DLIB PROFILE_NULL SOCKET THREAD LUA resource',
                exported_symbols = ['ResourceProviderArchive', 'ResourceProviderZip', 'ResourceProviderFile'],
                target       = 'test_provider_multi',
                source       = 'test_provider_multi.cpp',)

    # ******************************************************************************************************************************
    # Resource cache tests

    bld.program(features     = 'cxx test',
                includes     = '.. ../../proto',
                use          = 'TESTMAIN DDF DLIB PROFILE_NULL SOCKET THREAD LUA resource',
                exported_symbols = ['ResourceProviderArchive'],
                target       = 'test_resource_chunk_cache',
                source       = 'test_resource_chunk_cache.cpp',)

    # ******************************************************************************************************************************
    # Integration tests

    bld.program(features     = 'cxx embed test',
                includes     = '.. ../../proto',
                use          = 'TESTMAIN DDF DLIB PROFILE_NULL SOCKET THREAD LUA resource',
                proto_gen_py = True,
                target       = 'test_resource_archive',
                source       = 'test_resource_archive.cpp',
                embed_source = embed_source + 'resources.public resources.manifest_hash'.split())

    bld.program(features     = 'cxx test',
                includes     = '.. ../../proto',
                use          = 'TESTMAIN DDF DLIB PROFILE_NULL SOCKET THREAD LUA resource',
                exported_symbols = ['ResourceProviderFile', 'ResourceProviderZip', 'ResourceProviderArchive'],
                target       = 'test_resource_mounts',
                source       = 'test_resource_mounts.cpp',
                embed_source = embed_source + 'resources.public resources.manifest_hash'.split())

    bld.program(features     = ['cxx', 'embed', 'test'] + skip_http_test,
                includes     = '.. ../../proto',
                defines      = defines,
                use          = 'TESTMAIN DDF DLIB PROFILE_NULL SOCKET THREAD LUA resource',
                web_libs     = ['library_sys.js'],
                proto_gen_py = True,
                exported_symbols = ['ResourceProviderFile', 'ResourceProviderHttp', 'ResourceProviderArchive'],
                target       = 'test_resource',
                source       = 'test_resource.cpp test_resource_ddf.proto test.cont_pb test01.foo_pb test02.foo_pb self_referring.cont_pb root_loop.cont_pb child_loop.cont_pb many_refs.cont_pb',
                embed_source = 'resources.arci resources.arcd resources.dmanifest')
